package main

import (
	"bufio"
	"bytes"
	"encoding/csv"
	"fmt"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	for true {
		fmt.Print("请输入需要批量重命名的文件夹目录（输入'exit'退出）：")
		filePath, _ := reader.ReadString('\n')
		filePath = strings.TrimSpace(filePath)
		if filePath == "exit" {
			break
		}
		fmt.Println("")
		fmt.Println("")
		fmt.Print("请输入生成文件名目录表格的文件夹目录（输入'exit'退出）：")
		csvPath, _ := reader.ReadString('\n')
		csvPath = strings.TrimSpace(csvPath)
		if csvPath == "exit" {
			break
		}
		fmt.Println("")
		fmt.Println("")
		fmt.Print("是否读取指定文件名生成目录表格(yes/no)（输入'exit'退出）：")
		isChange, _ := reader.ReadString('\n')
		isChange = strings.TrimSpace(isChange)
		if isChange == "exit" {
			break
		}
		if isChange == "是" || isChange == "yes" {
			fmt.Println("")
			fmt.Println("")
			doRename(filePath, csvPath)
		}
		fmt.Println("")
		fmt.Println("")
		fmt.Print("是否开始批量修改文件名(yes/no)（输入'exit'退出）：")
		isChange1, _ := reader.ReadString('\n')
		isChange1 = strings.TrimSpace(isChange1)
		if isChange1 == "exit" {
			break
		}
		if isChange1 == "是" || isChange1 == "yes" {
			fmt.Println("")
			fmt.Println("")
			doChange(filePath, csvPath)
		}
	}
}

// 执行批量修改文件名
func doRename(filePath string, csvPath string) {
	//读取指定目录下的所有文件
	var pathFileNameArr []string
	fileName, err := getTrueAllFileNames(filePath, pathFileNameArr)
	if err != nil {
		fmt.Println("读取指定目录下的文件名错误", err.Error())
	}
	//导出表格
	cErr := createCsvFile(csvPath, fileName)
	if cErr != nil {
		fmt.Println("文件名导出表格错误", cErr.Error())
	}
	fmt.Println("生成表格成功，请求修改表格内容！")
}

func doChange(filePath string, csvPath string) {
	//读取表格中修改后的数据
	changeData, rErr := readCsvFile(csvPath)
	if rErr != nil {
		fmt.Println("读取表格内容错误", rErr.Error())
	}
	//修改文件名
	cfErr := changeFileName(filePath, changeData)
	if cfErr != nil {
		fmt.Println("重命名文件错误", cfErr.Error())
	}
}

// 获取指定目录下所有文件的文件名并存入切片
func getTrueAllFileNames(directory string, fileNames []string) ([]string, error) {
	err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 如果是文件而不是目录，则将文件名添加到切片中
		if !info.IsDir() {
			name := info.Name()
			trimmed := strings.TrimSpace(name)
			noTabs := strings.ReplaceAll(trimmed, "\t", "")
			fileNames = append(fileNames, noTabs)
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	return fileNames, nil
}

/**
 * @Description:将文件名生成为csv
 * @param csvPath
 * @param fileName
 * @author liyuan
 */
func createCsvFile(csvPath string, fileName []string) error {
	if csvPath == "" {
		return fmt.Errorf("表格生成目录不能为空")
	}
	if len(fileName) == 0 {
		return fmt.Errorf("目录下不存在文件")
	}
	// 要写入的数据
	data := make([][]string, 0)
	for _, value := range fileName {
		tmpData := []string{value}
		data = append(data, tmpData)
	}

	fullPath := filepath.Join(csvPath, "文件名目录.csv")
	fmt.Println("开始创建文件名目录表格", fullPath)
	fmt.Println("..........")
	fmt.Println(".........")
	fmt.Println("....")
	fmt.Println(".")
	// 创建一个新的CSV文件
	file, err := os.Create(fullPath)
	if err != nil {
		return err
	}
	defer file.Close()

	// 创建一个CSV写入器
	writer := csv.NewWriter(file)
	defer writer.Flush()

	// 将数据写入CSV文件
	for _, row := range data {
		err := writer.Write(row)
		if err != nil {
			return err
		}
	}
	return nil
}

/**
 * @Description:读取指定csv的内容
 * @param csvPath
 * @author liyuan
 */
func readCsvFile(csvPath string) ([][]string, error) {
	data := make([][]string, 0)
	fullPath := filepath.Join(csvPath, "文件名目录.csv")
	// 打开CSV文件
	//file, err := os.Open(fullPath)
	file, err := ioutil.ReadFile(fullPath)
	if err != nil {
		return data, err
	}
	//defer file.Close()

	// 创建一个CSV阅读器
	//reader := csv.NewReader(file)
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// 读取所有行
	records, err := reader.ReadAll()
	if err != nil {
		return data, err
	}
	data = records
	return data, nil
}

/**
 * @Description:修改文件名
 * @param filePath
 * @param fileName
 * @return error
 * @author liyuan
 */
func changeFileName(filePath string, fileName [][]string) error {
	if len(fileName) == 0 {
		return fmt.Errorf("表格内容为空，请检查文件名目录表格")
	}
	if filePath == "" {
		return fmt.Errorf("请设置需要修改文件名的文件目录")
	}
	errStr := ""
	for _, value := range fileName {
		if len(value) <= 1 || value[0] == "" || value[1] == "" {
			continue
		}
		oldTmpFileName := removeChineseSpaces(value[0])
		tmpFileName := removeChineseSpaces(value[1])
		if tmpFileName == "" || oldTmpFileName == "" {
			continue
		}

		oldFullPath := filepath.Join(filePath, oldTmpFileName)
		newFullPath := filepath.Join(filePath, tmpFileName)

		_, err := os.Stat(oldFullPath)
		if os.IsNotExist(err) {
			fmt.Printf("文件 %s 不存在\n", oldFullPath)
			return err
		}

		fmt.Println("老文件", oldFullPath)
		fmt.Println("新文件", newFullPath)
		fmt.Println("开始修改中。。。。")
		err = os.Rename(oldFullPath, newFullPath)

		if err != nil {
			errStr += fmt.Sprintf("%s\n", err.Error())
		}
	}
	if errStr != "" {
		return fmt.Errorf(errStr)
	}

	return nil
}

// 去除文件中文空格
func removeChineseSpaces(input string) string {
	var result []rune

	for _, r := range input {
		if r == '　' { // 这里是全角空格的Unicode码点
			continue
		}

		result = append(result, r)
	}

	return string(result)
}
